# -*- coding: UTF-8 -*-
'''
@Project ：push_rk
@File ：app.py
@IDE ：PyCharm
@Author ：苦瓜
@Date ：2025/9/24 10:57
@Note: Something beautiful is about to happen !
'''
from flask import Flask, request, render_template
from model import AlexNet, MyBaseCNN
from keras.src.utils import load_img, img_to_array

app = Flask(__name__)  # 初始化app

model = AlexNet()  # 初始化模型
model.build(input_shape=(None, 32, 32, 3))  # 构建模型
model.load_weights("model.weights.h5")  # 加载权重信息

def read_image(path):
    """ 读取图片 """
    image = load_img(path, target_size=(1, 32, 32, 3))
    image = img_to_array(image).reshape(1, 32, 32, 3).astype('float32') / 255.
    return image

@app.route('/')
def home():
    return render_template('home.html')

@app.route("/predict", methods=['POST'])
def predict():
    try:
        if request.method == 'POST':
            input_file = request.files['file']
            # 判断是否存在文件数据对象
            if not input_file:
                return render_template('error.html', error='file is None object')
            # 存储
            path_ = f"static/images/{input_file.filename}"
            input_file.save(path_)  # 保存
            # 处理获取得图片
            image = read_image(path_)
            # 对图片进行预测
            y_pred_num = model.predict(image).argmax()
            y_pred_cls = MyBaseCNN.predict_cls(y_pred_num)  # 返回类别对象
            return render_template('predict.html', user_image=path_, product=y_pred_cls)
    except Exception as e:
        return render_template('error.html', error=str(e))


if __name__ == '__main__':
    app.run(host='0.0.0.0', port=6008, debug=True)

# 1)	应用程序初始化
# 应用程序应能够成功加载并初始化Flask服务器。
# 应用程序应加载预训练的AlexNet模型及其权重，模型应针对CIFAR-100数据集进行训练。
# 2)	主页显示
# 应用程序应提供一个主页（/路由），该页面包含上传图像的表单。
# 主页应渲染home.html模板，该模板包含文件上传控件和提交按钮。
# 3)	图像上传
# 应用程序应能够接收通过POST请求上传的图像文件。
# 上传的文件应保存在服务器上的指定目录（例如static/images）中。
# 4)	图像预测
# 应用程序应能够读取上传的图像文件，并将其转换为模型可接受的格式（例如，32x32像素，3通道，归一化到[0,1]范围）。
# 应用程序应使用加载的AlexNet模型对图像进行预测，并获取最可能的类别索引。
# 应用程序应能够将类别索引映射到具体的类别名称（使用提供的product_dict字典）。
# 5)	结果显示
# 预测完成后，应用程序应渲染predict.html模板，并传递预测结果（类别名称）和上传的图像路径作为模板变量。
# predict.html模板应显示预测结果和上传的图像。
# 6)	错误处理
# 如果上传的文件不是有效的图像文件或无法读取，应用程序应捕获异常并显示相应的错误消息。
# 如果在预测过程中发生任何错误，应用程序应捕获异常并返回适当的错误响应。
# 7)	调试模式
# 应用程序应支持在调试模式下运行，以便在开发过程中提供详细的错误跟踪和日志信息。
# 3.	前端上传图像页功能约束
# 1)	页面标题:
# 页面标题应为“Upload Apparel Image”。
# 2)	页面内容:
# 页面应包含一个标题“Clothing Prediction”。
# 3)	文件上传表单:
# 页面应包含一个表单，表单的提交方式应为POST，并且表单的数据编码类型应为multipart/form-data，以支持文件上传。
# 表单的提交地址应为/predict。
# 4)	文件输入:
# 表单中应包含一个文件输入字段，允许用户选择文件。
# 文件输入字段的名称应为file。
# 5)	提交按钮:
# 表单中应包含一个提交按钮，按钮的文本应为“Upload”。
# 4.	前端预测页功能约束
# 1)	页面标题：页面标题应为“currency Prediction”。
# 2)	图像显示：
# 页面应显示一个图像。
# 图像的路径应从变量user_image中获取。
# 3)	标题显示：
# 页面应显示一个标题。
# 标题的内容应从变量product中获取，格式为“i think that this is [product名称]”。
# 4)	表单功能：
# 页面应包含一个表单。
# 表单的提交地址应为“http://127.0.0.1:6008/”。
# 表单应包含一个提交按钮，按钮的文字为“predict another clothing ?”。
# 5)	页面结构：
# 所有内容应包含在一个<div>元素中。
# 图像、标题和表单都应位于这个<div>元素内。
# 这些约束确保了HTML页面的基本功能和布局符合预期。
